{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import h5py\n",
    "from lr_utils import load_dataset\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(12288, 209)\n",
      "(1, 209)\n",
      "(12288, 50)\n",
      "(1, 50)\n"
     ]
    }
   ],
   "source": [
    "# 导入数据，“_orig”代表这里是原始数据，我们还要进一步处理才能使用：\n",
    "train_set_x_orig, train_set_y, test_set_x_orig, test_set_y, classes = load_dataset()\n",
    "#由数据集获取一些基本参数，如训练样本数m，图片大小：\n",
    "m_train = train_set_x_orig.shape[0]  #训练集大小209\n",
    "m_test = test_set_x_orig.shape[0]    #测试集大小50\n",
    "num_px = train_set_x_orig.shape[1]  #图片宽度64，大小是64×64\n",
    "#将图片数据向量化（扁平化）：\n",
    "train_set_x_flatten = train_set_x_orig.reshape(train_set_x_orig.shape[0],-1).T\n",
    "test_set_x_flatten = test_set_x_orig.reshape(test_set_x_orig.shape[0],-1).T\n",
    "#对数据进行标准化：\n",
    "train_set_x = train_set_x_flatten/255.\n",
    "test_set_x = test_set_x_flatten/255.\n",
    "print(train_set_x.shape)\n",
    "print(train_set_y.shape)\n",
    "print(test_set_x.shape)\n",
    "print(test_set_y.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def sigmoid(z):\n",
    "    a = 1/(1+np.exp(-z))\n",
    "    return a\n",
    "\n",
    "def initialize_with_zeros(dim):\n",
    "    w = np.zeros((dim,1))\n",
    "    b = 0\n",
    "    return w,b\n",
    "\n",
    "def propagate(w, b, X, Y):\n",
    "    \"\"\"\n",
    "    传参:\n",
    "    w -- 权重, shape： (num_px * num_px * 3, 1)\n",
    "    b -- 偏置项, 一个标量\n",
    "    X -- 数据集，shape： (num_px * num_px * 3, m),m为样本数\n",
    "    Y -- 真实标签，shape： (1,m)\n",
    "\n",
    "    返回值:\n",
    "    cost， dw ，db，后两者放在一个字典grads里\n",
    "    \"\"\"\n",
    "    #获取样本数m：\n",
    "    m = X.shape[1]\n",
    "\n",
    "    # 前向传播 ：\n",
    "    A = sigmoid(np.dot(w.T,X)+b)    #调用前面写的sigmoid函数    \n",
    "    cost = -(np.sum(Y*np.log(A)+(1-Y)*np.log(1-A)))/m                 \n",
    "\n",
    "    # 反向传播：\n",
    "    dZ = A-Y\n",
    "    dw = (np.dot(X,dZ.T))/m\n",
    "    db = (np.sum(dZ))/m\n",
    "\n",
    "    #返回值：\n",
    "    grads = {\"dw\": dw,\n",
    "             \"db\": db}\n",
    "\n",
    "    return grads, cost\n",
    "\n",
    "def optimize(w, b, X, Y, num_iterations, learning_rate, print_cost = False):\n",
    "    #定义一个costs数组，存放每若干次迭代后的cost，从而可以画图看看cost的变化趋势：\n",
    "    costs = []\n",
    "    #进行迭代：\n",
    "    for i in range(num_iterations):\n",
    "        # 用propagate计算出每次迭代后的cost和梯度：\n",
    "        grads, cost = propagate(w,b,X,Y)\n",
    "        dw = grads[\"dw\"]\n",
    "        db = grads[\"db\"]\n",
    "\n",
    "        # 用上面得到的梯度来更新参数：\n",
    "        w = w - learning_rate*dw\n",
    "        b = b - learning_rate*db\n",
    "\n",
    "        # 每100次迭代，保存一个cost看看：\n",
    "        if i % 100 == 0:\n",
    "            costs.append(cost)\n",
    "\n",
    "        # 这个可以不在意，我们可以每100次把cost打印出来看看，从而随时掌握模型的进展：\n",
    "        if print_cost and i % 100 == 0:\n",
    "            print (\"Cost after iteration %i: %f\" %(i, cost))\n",
    "    #迭代完毕，将最终的各个参数放进字典，并返回：\n",
    "    params = {\"w\": w,\n",
    "              \"b\": b}\n",
    "    grads = {\"dw\": dw,\n",
    "             \"db\": db}\n",
    "    return params, grads, costs\n",
    "\n",
    "def predict(w,b,X):\n",
    "    m = X.shape[1]\n",
    "    Y_prediction = np.zeros((1,m))\n",
    "\n",
    "    A = sigmoid(np.dot(w.T,X)+b)\n",
    "    for  i in range(m):\n",
    "        if A[0,i]>0.5:\n",
    "            Y_prediction[0,i] = 1\n",
    "        else:\n",
    "            Y_prediction[0,i] = 0\n",
    "\n",
    "    return Y_prediction"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def logistic_model(X_train,Y_train,X_test,Y_test,learning_rate=0.1,num_iterations=2000,print_cost=False):\n",
    "    #获特征维度，初始化参数：\n",
    "    dim = X_train.shape[0]\n",
    "    W,b = initialize_with_zeros(dim)\n",
    "\n",
    "    #梯度下降，迭代求出模型参数：\n",
    "    params,grads,costs = optimize(W,b,X_train,Y_train,num_iterations,learning_rate,print_cost)\n",
    "    W = params['w']\n",
    "    b = params['b']\n",
    "\n",
    "    #用学得的参数进行预测：\n",
    "    prediction_train = predict(W,b,X_train)\n",
    "    prediction_test = predict(W,b,X_test)\n",
    "\n",
    "    #计算准确率，分别在训练集和测试集上：\n",
    "    accuracy_train = 1 - np.mean(np.abs(prediction_train - Y_train))\n",
    "    accuracy_test = 1 - np.mean(np.abs(prediction_test - Y_test))\n",
    "    print(\"Accuracy on train set:\",accuracy_train )\n",
    "    print(\"Accuracy on test set:\",accuracy_test )\n",
    "\n",
    "   #为了便于分析和检查，我们把得到的所有参数、超参数都存进一个字典返回出来：\n",
    "    d = {\"costs\": costs,\n",
    "         \"Y_prediction_test\": prediction_test , \n",
    "         \"Y_prediction_train\" : prediction_train , \n",
    "         \"w\" : W, \n",
    "         \"b\" : b,\n",
    "         \"learning_rate\" : learning_rate,\n",
    "         \"num_iterations\": num_iterations,\n",
    "         \"train_acy\":accuracy_train,\n",
    "         \"test_acy\":accuracy_test\n",
    "        }\n",
    "    return d"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Cost after iteration 0: 0.693147\n",
      "Cost after iteration 100: 0.584508\n",
      "Cost after iteration 200: 0.466949\n",
      "Cost after iteration 300: 0.376007\n",
      "Cost after iteration 400: 0.331463\n",
      "Cost after iteration 500: 0.303273\n",
      "Cost after iteration 600: 0.279880\n",
      "Cost after iteration 700: 0.260042\n",
      "Cost after iteration 800: 0.242941\n",
      "Cost after iteration 900: 0.228004\n",
      "Cost after iteration 1000: 0.214820\n",
      "Cost after iteration 1100: 0.203078\n",
      "Cost after iteration 1200: 0.192544\n",
      "Cost after iteration 1300: 0.183033\n",
      "Cost after iteration 1400: 0.174399\n",
      "Cost after iteration 1500: 0.166521\n",
      "Cost after iteration 1600: 0.159305\n",
      "Cost after iteration 1700: 0.152667\n",
      "Cost after iteration 1800: 0.146542\n",
      "Cost after iteration 1900: 0.140872\n",
      "Accuracy on train set: 0.9904306220095693\n",
      "Accuracy on test set: 0.7\n"
     ]
    }
   ],
   "source": [
    "d = logistic_model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 2000, learning_rate = 0.005, print_cost = True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0.6931471805599453,\n",
       " 0.5845083636993088,\n",
       " 0.46694904094655476,\n",
       " 0.3760068669480209,\n",
       " 0.33146328932825125,\n",
       " 0.30327306747438293,\n",
       " 0.27987958658260487,\n",
       " 0.2600421369258757,\n",
       " 0.24294068467796617,\n",
       " 0.2280042225672606,\n",
       " 0.2148195137844964,\n",
       " 0.20307819060644988,\n",
       " 0.19254427716706862,\n",
       " 0.18303333796883506,\n",
       " 0.17439859438448874,\n",
       " 0.1665213970540033,\n",
       " 0.15930451829756614,\n",
       " 0.15266732471296504,\n",
       " 0.14654223503982342,\n",
       " 0.14087207570310156]"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "d['costs']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0xf733eeebe0>]"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0xf733fc3e80>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.plot(np.squeeze(d['costs']))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
